////////////////////////////////////////////////////////////////////////////////////////////////////
/// @file   CollabRCBotUnitTests\TestLhsTreeNode.h
///
/// @brief  Defines the tests for CollabRC::Bot::AI::LhsTreeNode
////////////////////////////////////////////////////////////////////////////////////////////////////

#include <cxxtest/TestSuite.h>
#include "../CollabRCBot/LhsTreeNode.h"
#include "MockConstantTreeNode.h"
#include "MockOperationTreeNode.h"

class TestLhsTreeNode : public CxxTest::TestSuite
{
private:
    MockConstantTreeNode m_lhs, m_rhs;
public:
    TestLhsTreeNode():m_lhs(4),m_rhs(8) { };

    /** @brief tests the operation of PerformOperation() */
    void TestPerformOperation()
    {
        CollabRC::Bot::AI::LhsTreeNode node(m_lhs, m_rhs);
        TS_ASSERT_EQUALS(node.PerformOperation(4.0f, 8.0f), 4.0f);
    }

    /** @brief tests the operation of Clone() */
    void TestClone()
    {
        CollabRC::Bot::AI::LhsTreeNode node(m_lhs, m_rhs);

        // Note: Cloning should return a clone of the branch, optimizing out this node
        MockConstantTreeNode *clone = dynamic_cast<MockConstantTreeNode*>(node.Clone());

        bool oldATOF = CxxTest::abortTestOnFail();
        CxxTest::setAbortTestOnFail(true);
        TS_ASSERT(clone != NULL);
        CxxTest::setAbortTestOnFail(oldATOF);
        
        TS_ASSERT_EQUALS(node.Compute(), clone->Compute());
        TS_ASSERT_THROWS_NOTHING(delete clone);

        // Sometimes optimization isn't possible
        MockOperationTreeNode op(m_lhs, m_rhs);
        CollabRC::Bot::AI::LhsTreeNode node2(op);
        CollabRC::Bot::AI::LhsTreeNode *cloneNode = dynamic_cast<CollabRC::Bot::AI::LhsTreeNode*>(node2.Clone());
        
        CxxTest::setAbortTestOnFail(true);
        TS_ASSERT(cloneNode != NULL);
        CxxTest::setAbortTestOnFail(oldATOF);

        TS_ASSERT_EQUALS(cloneNode->Compute(), m_lhs.Compute());
        TS_ASSERT_THROWS_NOTHING(delete cloneNode);
    }
};